iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
自我挑戰組

新手挑戰 picoCTF:資安入門紀錄系列 第 21

PW Crack 5 — 用字典 + 雜湊找密碼

  • 分享至 

  • xImage
  •  

土day來挑戰的題目:
https://ithelp.ithome.com.tw/upload/images/20251003/20178898vA4QwjGkBy.png
這題給了四個檔案:
level5.py(檢查器)
level5.flag.txt.enc(被 XOR 加密的 flag)
level5.hash.bin(正確密碼的 hash bytes)
dictionary.txt(可能的密碼字典)

預估流程(馬後炮):從題目或字典取得可能的密碼候選 → 用與檢查器同樣的 hash 方法將候選雜湊 → 與 level5.hash.bin 比對找出正確密碼 → 用該密碼當 key 做 XOR 還原 flag。


解題步驟與思路
一、先下載題目檔:
wget https://artifacts.picoctf.net/c/31/level5.py
wget https://artifacts.picoctf.net/c/31/level5.flag.txt.enc
wget https://artifacts.picoctf.net/c/31/level5.hash.bin
wget https://artifacts.picoctf.net/c/31/dictionary.txt
ls -1


二、先檢視 level5.py 看檢查邏輯(是否有直接的 pos_pw_list、使用哪種 hash):
cat level5.py

flag_enc = open('level5.flag.txt.enc', 'rb').read()
correct_pw_hash = open('level5.hash.bin', 'rb').read()


def hash_pw(pw_str):
    pw_bytes = bytearray()
    pw_bytes.extend(pw_str.encode())
    m = hashlib.md5()
    m.update(pw_bytes)
    return m.digest()


def level_5_pw_check():
    user_pw = input("Please enter correct password for flag: ")
    user_pw_hash = hash_pw(user_pw)
    
    if( user_pw_hash == correct_pw_hash ):
        print("Welcome back... your flag, user:")
        decryption = str_xor(flag_enc.decode(), user_pw)
        print(decryption)
        return
    print("That password is incorrect")

解讀重點:

  1. level5.hash.bin = 正確密碼的 MD5 bytes。
  2. 只要把候選密碼(題目可能給 pos_pw_list 或提供 dictionary.txt)用相同 hash_pw()(即 MD5)處理,和 level5.hash.bin 比對即可找到正確密碼。
  3. 找到密碼後,把它當作 str_xor 的 key 去解 level5.flag.txt.enc 就會得到 flag。

三、我使用的 Python 自動化判定腳本(把 dictionary 當候選,嘗試常見 hash 與少量變形):

python3 - <<'PY'
import hashlib,os,re

cands=[]
if os.path.exists('level5.py'):
    src=open('level5.py','r',encoding='utf-8',errors='ignore').read()
    m=re.search(r'pos_pw_list\s*=\s*\[([^\]]*)\]',src,re.S)
    if m:
        cands=re.findall(r"""['"]([^'"]+)['"]""", m.group(1))
if not cands:
    with open('dictionary.txt','r',encoding='utf-8',errors='ignore') as f:
        cands=[l.strip() for l in f if l.strip()]

target=open('level5.hash.bin','rb').read()
algs=['md5','sha1','sha256','sha512']

transforms=[lambda s:s, lambda s:s.lower(), lambda s:s.upper(), lambda s:s.strip()]
suffixes=['','1','123','!']

for i,p in enumerate(cands):
    if i%1000==0:
        print("試到候選 #",i)
    for tf in transforms:
        base=tf(p)
        for suf in suffixes:
            pw=base+suf
            for alg in algs:
                d=getattr(hashlib,alg)(pw.encode()).digest()
                if d==target:
                    print("FOUND:", pw, "alg:", alg)
                    raise SystemExit
print("No match found")
PY

https://ithelp.ithome.com.tw/upload/images/20251003/20178898z6tG5J04Af.png


四、找到密碼後,用 str_xor 邏輯解密 level5.flag.txt.enc(以下把 THE_PASSWORD 換成找到的密碼):

python3 - <<'PY'
def str_xor(secret, key):
    new_key = key
    i = 0
    while len(new_key) < len(secret):
        new_key = new_key + key[i]
        i = (i + 1) % len(key)
    return "".join([chr(ord(a) ^ ord(b)) for a,b in zip(secret,new_key)])

enc = open('level5.flag.txt.enc','rb').read()
try:
    s = enc.decode()
except:
    s = enc.decode('latin-1')

print(str_xor(s, "THE_PASSWORD"))
PY

https://ithelp.ithome.com.tw/upload/images/20251003/20178898CwzSUqHcaO.png
一頓操作後就得到正確Flag啦!
picoCTF{h45h_sl1ng1ng_36e992a6}


排錯小技巧
檢查 level5.py 是否對輸入做了前處理(strip/lower/replace、加 salt 等)。

看 level5.hash.bin 長度判斷 hash 類型:
16 bytes → MD5
20 bytes → SHA1
32 bytes → SHA256
64 bytes → SHA512
命令: wc -c level5.hash.bin(顯示 bytes)

若 enc.decode() 失敗,先用 latin-1 或直接以 bytes 做 XOR 再篩選 ASCII printable。


學習心得
這題是把字典、雜湊與 XOR 三個常見概念串在一起的好題型。
實務上最重要的習慣是「讀懂檔案和程式」,把題目提供的線索當作首選候選,然後用小腳本自動化驗證。
解題完成之後記得把步驟和常用腳本紀錄下來,下一次遇到類似題型會更快。


上一篇
PW Crack 4 — 比對雜湊再解密
下一篇
Enhance!(SVG)— 從隱藏的 SVG 拿到 flag
系列文
新手挑戰 picoCTF:資安入門紀錄23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言